
/*
 * @Author: your name
 * @Date: 2021-06-30 10:02:08
 * @LastEditTime: 2021-12-14 15:51:03
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \server\tcp_client.h
 */
//
// Created by 29019 on 2020/4/18.
//
#pragma once

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif

#include <WinSock2.h>

#ifdef linux
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define EVENT__HAVE_PTHREADS
#endif

#include<string.h>
#include <iostream>
#include <mutex>
#include <thread>
#include <functional>

using  namespace std;

class TcpClientLibevent {
public:
    typedef enum {
        UNCONNECTED,  // 未连接
		CONNECTING, //已经连接
        CONNECTED, //已经连接
        FAIL,       // 连接失败
        STOP,      // 初始状态
    }Status;

    class TcpClientObserver {
    public:
        virtual ~TcpClientObserver() { return; }
        mutex mMux;
        virtual void OnConnected() { return; };
        virtual void OnDisConnected(std::string) { return; };
        virtual void OnData(uint8_t* dat, uint64_t len) { return; };
        virtual void OnClose() { return; };
    };
    
    TcpClientLibevent(std::string addrinfo, int port, TcpClientObserver* p);
    ~TcpClientLibevent();

    friend class ClientCallback;
    int ConnectServer();
	int ConnectServerSync();

    bool Connected();
    int Dispatch();
    int OnTCPPackage(uint8_t*, uint16_t);
    int SetReconnect(bool);
    int SetObserver(TcpClientObserver*);
    int Close();
    int SendDataAsync(const char*, int len);
    int SendDataSync(const char*, int len);

    uint64_t SocketFd();

    Status mStatus;
    TcpClientObserver* mObserver;
private:
    bool mReConnect = false;
    int sendData(void*, size_t);
    struct event_base* mBase;
    struct bufferevent* mBev;
    struct sockaddr_in mSrv;
    std::thread* mThread;
    mutex mLock;          // 互斥锁
    uint64_t mByteSend;   // 发送字节数
    uint64_t mByteRecv;   // 接收字节数
    intptr_t mSocketFD;   // 操作系统原生socket
    std::mutex mMutex;    // 互斥锁
};


